﻿// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

using BootstrapBlazor.Components;
using BootstrapBlazor.DataAccess.SqlSugar;
using Microsoft.Extensions.Configuration;
using SqlSugar;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection;
using System.Xml.Linq;
using static Npgsql.Replication.PgOutput.Messages.RelationMessage;

namespace Microsoft.Extensions.DependencyInjection;

/// <summary>
/// BootstrapBlazor 服务扩展类
/// </summary>
public static class SqlSugarServiceCollectionExtensions
{
    /// <summary>
    /// 增加 SqlSugar 数据库操作服务
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public static ISqlSugarClient AddSqlSugar(this IServiceCollection services, string connectionString, DbType dbType,
        Action<ISqlSugarClient, ConnectionConfig> action = null)
    {
        StaticConfig.Check_StringIdentity = false;//不验证String Identity  BB默认是用string  作为key
        var config = new ConnectionConfig()
        {
            ConnectionString = connectionString,
            DbType = dbType,
            IsAutoCloseConnection = true,
            InitKeyType = InitKeyType.Attribute,
            ConfigureExternalServices = new ConfigureExternalServices()
            {
                EntityNameService = (type, entity) =>
                {
                    //表名称改动 //设置改动
                    if (type.GetCustomAttribute<TableAttribute>() is TableAttribute tableAttribute)
                    {
                        entity.DbTableName = tableAttribute.Name;
                    }
                    //增加表注释
                    if (type.GetCustomAttribute<DisplayAttribute>() is DisplayAttribute displayAttribute)
                    {
                        entity.TableDescription = displayAttribute.Name;
                    }
                },
                EntityService = (type, column) =>
                {
                    //列名称改动 设置改动

                    //检查是否为key
                    if (type.GetCustomAttribute<KeyAttribute>() is KeyAttribute keyAttribute)
                    {
                        column.IsPrimarykey = true;
                    }

                    //检查是否为自增列
                    if (type.GetCustomAttribute<DatabaseGeneratedAttribute>() is DatabaseGeneratedAttribute databaseGeneratedAttribute)
                    {
                        column.IsIdentity = databaseGeneratedAttribute.DatabaseGeneratedOption == DatabaseGeneratedOption.Identity;
                    }

                    if (type.GetCustomAttribute<DisplayAttribute>() is DisplayAttribute displayAttribute)
                    {
                        column.ColumnDescription = displayAttribute.Name;
                    }

                    //自动识别null
                    if (new NullabilityInfoContext().Create(type).WriteState is NullabilityState.Nullable)
                    {
                        column.IsNullable = true;
                    }

                    if (type.GetCustomAttribute<NotMappedAttribute>() is NotMappedAttribute)
                    {
                        column.IsIgnore = true;
                    }
                }
            }
        };
        var db = new SqlSugarScope(config, db => action?.Invoke(db, config));
        action?.Invoke(db, config);
        services.AddSingleton<ISqlSugarClient>(provider => db);

        services.AddScoped(typeof(IDataService<>), typeof(DefaultDataService<>));
        return db;
    }

    /// <summary>
    /// 自动按照程序集 新建表 或者更新表
    /// </summary>
    /// <param name="db">ISqlSugarClient</param>
    /// <param name="stringDefaultLength">数据库字符串默认长度nvarchar(254) 默认 254</param>
    public static void InitcomDatabase(this ISqlSugarClient db, int stringDefaultLength = 254)
    {
        //获取全部有效程序集
        var apptypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes());

        var tabletypes = apptypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsDefined(typeof(TableAttribute), false)).ToArray();
        //指定当方法 (在当前方法加上这行，这个方法里面会生效)
        db.CurrentConnectionConfig.MoreSettings = new ConnMoreSettings()
        {
            DisableNvarchar = true,
            SqlServerCodeFirstNvarchar = true,
        };
        db.CodeFirst.SetStringDefaultLength(stringDefaultLength).InitTables(tabletypes);
    }
}
